package com.btpn.custody.security.action;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.validation.SkipValidation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;

import com.btpn.custody.bean.ParameterBeans;
import com.btpn.custody.dao.IGroupRole;
import com.btpn.custody.dao.IUser;
import com.btpn.custody.entity.GroupRole;
import com.btpn.custody.entity.User;
import com.btpn.custody.security.model.UserModel;
import com.btpn.custody.security.service.IUserService;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;
import com.opensymphony.xwork2.validator.annotations.EmailValidator;
import com.opensymphony.xwork2.validator.annotations.ExpressionValidator;
import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator;
import com.opensymphony.xwork2.validator.annotations.StringLengthFieldValidator;
import com.opensymphony.xwork2.validator.annotations.Validations;
import com.opensymphony.xwork2.validator.annotations.ValidatorType;

@ParentPackage(value="custody")
@Results({
	@Result(name="input", location="t_user")
})
@Validations(
	requiredStrings = {
		@RequiredStringValidator(type = ValidatorType.SIMPLE, fieldName = "username", message = "Username must be filled"),
//		@RequiredStringValidator(type = ValidatorType.SIMPLE, fieldName = "password", message = "Password must be filled"),
        @RequiredStringValidator(type = ValidatorType.SIMPLE, fieldName = "email", message = "You must enter email")
    },
    emails = {
		@EmailValidator(type = ValidatorType.SIMPLE, fieldName = "email", message = "Email must valid")},
	stringLengthFields = {
		@StringLengthFieldValidator(type = ValidatorType.SIMPLE, trim = true, minLength="1" , maxLength = "50", fieldName = "username", message = "Username must contain at ${minLength} until ${maxLength} characters")
//		@StringLengthFieldValidator(type = ValidatorType.SIMPLE, minLength="5" , maxLength = "20", fieldName = "password", message = "Password must contain at ${minLength} until ${maxLength} characters")
	},
	expressions = {
//        @ExpressionValidator(expression = "password == confirmPassword", message = "Password and confirm password do not match"),
        @ExpressionValidator(expression = "chosedRole != -1", message = "Role must be choose")
    }
)
public class UserAction extends ActionSupport implements ServletRequestAware, Preparable {

	private static final long serialVersionUID = -2869738053486932185L;
	
	@Autowired
	private IGroupRole groupRoleDaoHibernate;
	
	@Autowired
	private ParameterBeans parameterBeans;
	
	@Autowired
	private IUser userDaoHibernate;

	@Autowired
	private IUserService userService;
	
	private HttpServletRequest request;
	private String action;		// N : new, E : edit
	
	private String username;
	private String password;
	private String confirmPassword;
	private String email;
	private Long areaId;
	private Boolean enabled;
	private Long chosedGroup;

	// parameter
	private Map<String, String> areaMap;
	private List<UserModel> userModels;
	private List<GroupRole> groupRoles;
	
	@SkipValidation
	@Action(value = "/listUser", results = { @Result(name="success", location="t_user") })
	public String execute() throws Exception {
				
		action = "N";
		setUsername(null);
		setPassword(null);
		setEmail(null);
		setAreaId(0L);
		setEnabled(false);
		setChosedGroup(null);
		
		return SUCCESS;
	}
	
	@Action(value = "/addOrUpdateUser", results = {	
			@Result(name="success", type="redirectAction", params = {"actionName", "listUser"} )
//			@Result(name="invalid.token", type="redirectAction", params = {"actionName", "checklist"}) 
	}
//			interceptorRefs = { @InterceptorRef("tokenSession") }
//			interceptorRefs = { @InterceptorRef(value = "custodyDefaultStack", params = { "tokenSession.includeMethods", "*"} ) }
//	interceptorRefs = { @InterceptorRef(value = "invalidToken", params = {"operationMode", "STORE"}) }
	)
	public String addOrUpdateUser() throws Exception {
		
		if (action.equals("N")) {		// create with validation
			
			// validate username regex
//			if (!MyRegexValidator.validateUsername(username)) {
//				addFieldError("username", "Username must in 0-9, a-z, _, - and length 5-20 characters");
//				return INPUT;
//			}
			
			// validate password regex
//			if (!MyRegexValidator.validatePassword(password)) {
//				addFieldError("password", "Password must contain 0-9, a-z and length 5-20 characters");
//				return INPUT;
//			}
			
			// validate username db
			User theUser = userDaoHibernate.get(username);
			if (theUser != null) {
				addFieldError("username", "Username already exist");
				return INPUT;
			}			
		}

		// validate areaId for non-admin
//		if ((chosedGroup != 1) && (areaId == -1)) {
//			addFieldError("areaId", "Area must choose");
//			
//			return INPUT;
//		}
		
		userService.createOrUpdateUser(username, password, email, areaId, enabled, chosedGroup, SecurityContextHolder.getContext().getAuthentication().getName());
		
		return SUCCESS;
	}

	@SkipValidation
	@Action(value = "/editUser", results = { 
			@Result(name="success", location="t_user"),			
			@Result(name="error", type="redirectAction", params = {"actionName", "listUser"})
	})
	public String editUser() throws Exception {
				
		String userId = getRequest().getParameter("user");
		if (userId != null) {
			User editedUser = userDaoHibernate.get(userId);	
			username = editedUser.getUsername();
			setEmail(editedUser.getEmail());
			if (editedUser.getArea() != null) {
				setAreaId(editedUser.getArea().getId());
			}
			chosedGroup = (editedUser.getGroupRole() != null) ? editedUser.getGroupRole().getId() : -1L;
			setEnabled(editedUser.isEnabled());
			
			action = "E";
			
			return SUCCESS;
		} else {
			return ERROR;
		}
	}

	@SkipValidation
	@Action(value = "/removeUser", results = { 
			@Result(name="success", type="redirectAction", params = {"actionName", "listUser"} )
	})
	public String removeUser() throws Exception {
		
		userService.deleteUser(getRequest().getParameter("user"), SecurityContextHolder.getContext().getAuthentication().getName());
		
		return SUCCESS;
	}

//	@SkipValidation
//	@Action(value = "/resetPassword", results = { 
//			@Result(name="success", location="t_user"),
//	})
//	public String resetPassword() throws Exception {
//		addActionMessage(userService.resetPassword(username));
//		
//		action = "N";
//		setUsername(null);
//		setPassword(null);
//		setEmail(null);
//		setAreaId(0L);
//		setEnabled(false);
//		setChosedGroup(null);
//		
//		return SUCCESS;
//	}
	
	@Override
	public void prepare() throws Exception {
		areaMap = parameterBeans.getmArea();
		userModels = userService.listUserModel();
		groupRoles = groupRoleDaoHibernate.findAll();
	}
	
	@Override
	public void setServletRequest(HttpServletRequest request) {
		this.request = request;
	}

	public HttpServletRequest getRequest() {
		return request;
	}
	
	public Map<String, String> getAreaMap() {
		return areaMap;
	}

	public void setAreaMap(Map<String, String> areaMap) {
		this.areaMap = areaMap;
	}

	public Long getChosedGroup() {
		return chosedGroup;
	}

	public void setChosedGroup(Long chosedGroup) {
		this.chosedGroup = chosedGroup;
	}

	public List<UserModel> getUserModels() {
		return userModels;
	}

	public void setUserModels(List<UserModel> userModels) {
		this.userModels = userModels;
	}
	
	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public Long getAreaId() {
		return areaId;
	}

	public void setAreaId(Long areaId) {
		this.areaId = areaId;
	}

	public Boolean getEnabled() {
		return enabled;
	}

	public void setEnabled(Boolean enabled) {
		this.enabled = enabled;
	}

	public String getAction() {
		return action;
	}

	public void setAction(String action) {
		this.action = action;
	}

	public String getConfirmPassword() {
		return confirmPassword;
	}

	public void setConfirmPassword(String confirmPassword) {
		this.confirmPassword = confirmPassword;
	}

	public List<GroupRole> getGroupRoles() {
		return groupRoles;
	}

	public void setGroupRoles(List<GroupRole> groupRoles) {
		this.groupRoles = groupRoles;
	}
}
